# -*- coding: utf-8 -*-
'''
Created on 10.05.2011

@author: Mukhamed Karanashev
'''

import actions
import contexts
from django import http
from django.conf.urls.defaults import patterns, url
from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from django.contrib.auth.models import User, Group
from django.core.exceptions import PermissionDenied
from django.db.models import get_app, get_models
from django.views.decorators.cache import never_cache
from dummy import models

def _update_context(extra_context, context):
    if extra_context is None:
        extra_context = context
    else:
        extra_context.update(context)
    return extra_context

class AristoclesModelAdmin(admin.ModelAdmin):
    
    def has_change_permission(self, request, obj=None):
        if hasattr(self, 'allow_change') and self.allow_change:
            return True
        return super(AristoclesModelAdmin, self).has_change_permission(request, obj)
    
    def has_view_permission(self, request, obj=None):
        return request.user.has_perm(self.opts.app_label + '.view_%s' % self.opts.module_name)
    
    def has_list_permission(self, request):
        return request.user.has_perm(self.opts.app_label + '.list_%s' % self.opts.module_name)
    
    def get_model_perms(self, request):
        perms = super(AristoclesModelAdmin, self).get_model_perms(request)
        perms.update({
            'view': self.has_view_permission(request),
            'list': self.has_list_permission(request),
        })
        return perms
    
    def get_actions(self, request):
        actions = super(AristoclesModelAdmin, self).get_actions(request)
        ans = {}
        for action in actions:
            if request.user.is_superuser:
                ans[action] = actions[action]
            elif hasattr(actions[action][0], "permission"):
                if request.user.has_perm(getattr(actions[action][0], "permission")):
                    ans[action] = actions[action]
            else:
                if super(AristoclesModelAdmin, self).has_delete_permission(request, None):
                    ans[action] = actions[action]
        return ans
    
    def change_view(self, request, object_id, extra_context=None):
        obj = self.get_object(request, admin.util.unquote(object_id))
        if not self.has_change_permission(request, obj) and (request.method == 'POST'
                or not self.has_view_permission(request, obj)):
            raise PermissionDenied
        extra_context = _update_context(extra_context, {
            'read_only': not self.has_change_permission(request, obj)
        })
        self.allow_change = True
        ans = super(AristoclesModelAdmin, self).change_view(request, object_id, extra_context)
        self.allow_change = False
        return ans
    
    def changelist_view(self, request, extra_context=None):
#        if not self.has_change_permission(request, None) and (request.method == 'POST'
#                or not self.has_list_permission(request)):
        if not (self.has_change_permission(request, None) or self.has_list_permission(request)):
            raise PermissionDenied
        extra_context = _update_context(extra_context, {
            'request': request
        })
        self.allow_change = True
        ans = super(AristoclesModelAdmin, self).changelist_view(request, extra_context)
        self.allow_change = False
        return ans
    
    def get_readonly_fields(self, request, obj=None):
        if super(AristoclesModelAdmin, self).has_change_permission(request, obj) or super(AristoclesModelAdmin, self).has_add_permission(request):
            return self.readonly_fields
        else:
            ans = [f.name for f in self.opts.fields]
            ans.remove(self.opts.pk.name)
            return ans
    
    def _update_context(extra_context, context):
        if extra_context is None:
            extra_context = context
        else:
            extra_context.update(context)
        return extra_context

class ScholarshipModelAdmin(AristoclesModelAdmin):
    
    def changelist_view(self, request, extra_context=None):
        extra_context = _update_context(extra_context, {
            "actions_href": "../../actions/",
            "actions": []
        })
        if request.user.is_superuser or request.user.has_perm(actions.DistributeScholarshipAction.permission):
            extra_context["actions"].append({
                "href": actions.DistributeScholarshipAction.url + "/",
                "verbose_name": actions.DistributeScholarshipAction.verbose_name,
            })
        if request.user.is_superuser or request.user.has_perm(actions.ScholarshipBySemesterAction.permission):
            extra_context["actions"].append({
                "href": actions.ScholarshipBySemesterAction.url + "/",
                "verbose_name": actions.ScholarshipBySemesterAction.verbose_name,
            })
        return super(ScholarshipModelAdmin, self).changelist_view(request, extra_context)
    
    def get_urls(self):
        return patterns('aristocles.dummy.views',
            url('^' + actions.ScholarshipBySemesterAction.url + '/$', 'scholarship_by_semester'),
            url('^' + actions.DistributeScholarshipAction.url + '/$', 'distribute_scholarship'),
            url('^%s/auto/$' % actions.DistributeScholarshipAction.url, 'calc_scholarship'),
            url('^%s/done/$' % actions.DistributeScholarshipAction.url, 'give_scholarship'),
            url('^%s/delete/(?P<student>\d+)/$' % actions.DistributeScholarshipAction.url, 'delete_scholarship_student'),
            url('^%s/edit/(?P<student>\d+)/$' % actions.DistributeScholarshipAction.url, 'edit_scholarship_student'),
            url('^%s/edit/(?P<student>\d+)/(?P<clazz>\d+)/$' % actions.DistributeScholarshipAction.url, 'addelete_scholarship_student'),
            url('^%s/(?P<student>\d+)/$' % actions.DistributeScholarshipAction.url, 'distribute_scholarship'),
        ) + super(ScholarshipModelAdmin, self).get_urls()
    
    def has_view_permission(self, request, obj=None):
        if obj is not None and obj.student.user == request.user:
            return True
        return super(ScholarshipModelAdmin, self).has_view_permission(request, obj)

class SessionModelAdmin(AristoclesModelAdmin):
    
    list_filter = ('speciality',)
    
    def get_urls(self):
        return patterns('aristocles.dummy.views',
            url('^' + actions.SessionResultAction.url + '/$', 'result_session'),
        ) + super(SessionModelAdmin, self).get_urls()
    
    def change_view(self, request, object_id, extra_context=None):
        if request.user.is_superuser or request.user.has_perm(actions.SessionResultAction.permission):
            extra_context = _update_context(extra_context, {
                "actions_href": "../../../actions/",
                "actions": [{
                    "href": "../%s/?session=%s" % (
                        actions.SessionResultAction.url,
                        object_id),
                    "verbose_name": actions.SessionResultAction.verbose_name,
                }],
            })
        return super(SessionModelAdmin, self).change_view(request, object_id, extra_context)
    
    def changelist_view(self, request, extra_context=None):
        if request.user.is_superuser or request.user.has_perm(actions.SessionResultAction.permission):
            extra_context = _update_context(extra_context, {
                "actions_href": "../../actions/",
                "actions": [{
                    "href": actions.SessionResultAction.url + "/",
                    "verbose_name": actions.SessionResultAction.verbose_name,
                }]
            })
        return super(SessionModelAdmin, self).changelist_view(request, extra_context)

class SpecialityModelAdmin(AristoclesModelAdmin):
    
    list_filter = ('faculty',)

class StudentModelAdmin(AristoclesModelAdmin):
    
    list_filter = ('group',)
    actions = (actions.distribute_scholarship, actions.distribute_welfare)
    
    def get_urls(self):
        return patterns('aristocles.dummy.views',
            url('^' + actions.StudentsByGroupAction.url + '/$', 'students_by_group'),
            url('^' + actions.StudentsByGroupAction.url + r'/(?P<group>\d+)/$', 'students_by_group'),
        ) + super(StudentModelAdmin, self).get_urls()
    
    def change_view(self, request, object_id, extra_context=None):
        extra_context = _update_context(extra_context, {
            "actions_href": "../../actions/",
            "actions": []
        })
        if request.user.is_superuser or request.user.has_perm(actions.DistributeWelfareAction.permission):
            c = None
            try:
                c = models.Committee.objects.get(user=request.user)
            except:
                pass
            if request.user.is_superuser or c is None or c.faculty == models.Students.objects.get(pk=object_id).faculty:
                extra_context["actions"].append({
                    "href": "../../%s/%s/%s/" % (
                            actions.DistributeWelfareAction.model._meta.module_name,
                            actions.DistributeWelfareAction.url,
                            object_id),
                    "verbose_name": actions.DistributeWelfareAction.verbose_name,
                })
        if request.user.is_superuser or request.user.has_perm(actions.DistributeScholarshipAction.permission):
            c = None
            try:
                c = models.Committee.objects.get(user=request.user)
            except:
                pass
            if request.user.is_superuser or c is None or c.faculty == models.Students.objects.get(pk=object_id).faculty:
                extra_context["actions"].append({
                    "href": "../../%s/%s/%s/" % (
                            actions.DistributeScholarshipAction.model._meta.module_name,
                            actions.DistributeScholarshipAction.url,
                            object_id),
                    "verbose_name": actions.DistributeScholarshipAction.verbose_name,
                })
        return super(StudentModelAdmin, self).change_view(request, object_id, extra_context)
    
    def changelist_view(self, request, extra_context=None):
        if request.user.is_superuser or request.user.has_perm(actions.StudentsByGroupAction.permission):
            extra_context = _update_context(extra_context, {
                "actions_href": "../../actions/",
                "actions": [{
                    "href": actions.StudentsByGroupAction.url + "/",
                    "verbose_name": actions.StudentsByGroupAction.verbose_name,
                }]
            })
        return super(StudentModelAdmin, self).changelist_view(request, extra_context)

class StudentClassModelAdmin(AristoclesModelAdmin):
    
    actions = (actions.distribute_scholarship, actions.distribute_welfare)

class StudentGroupModelAdmin(AristoclesModelAdmin):
    
    def change_view(self, request, object_id, extra_context=None):
        extra_context = _update_context(extra_context, {
            "actions_href": "../../../actions/",
            "actions": []
        })
        if request.user.is_superuser or request.user.has_perm(actions.StudentsByGroupAction.permission):
            extra_context["actions"].append({
                "href": "../../%s/%s/%s/" % (
                        actions.StudentsByGroupAction.model._meta.module_name,
                        actions.StudentsByGroupAction.url,
                        object_id),
                "verbose_name": actions.StudentsByGroupAction.verbose_name,
            })
        if request.user.is_superuser or request.user.has_perm(actions.SessionResultAction.permission):
            extra_context["actions"].append({
                "href": "../../%s/%s/?group=%s" % (
                        actions.SessionResultAction.model._meta.module_name,
                        actions.SessionResultAction.url,
                        object_id),
                "verbose_name": actions.SessionResultAction.verbose_name,
            })
        return super(StudentGroupModelAdmin, self).change_view(request, object_id, extra_context)

class WelfareModelAdmin(AristoclesModelAdmin):
    
    def get_urls(self):
        return patterns('aristocles.dummy.views',
            url('^' + actions.DistributeWelfareAction.url + '/$', 'distribute_welfare'),
            url('^%s/auto/$' % actions.DistributeWelfareAction.url, 'calc_welfare'),
            url('^%s/delete/(?P<student>\d+)/$' % actions.DistributeWelfareAction.url, 'delete_welfare_student'),
            url('^%s/edit/(?P<student>\d+)/$' % actions.DistributeWelfareAction.url, 'edit_welfare_student'),
            url('^%s/edit/(?P<student>\d+)/(?P<clazz>\d+)/$' % actions.DistributeWelfareAction.url, 'addelete_welfare_student'),
            url('^%s/edit/(?P<student>\d+)/request/(?P<req>\d+)/$' % actions.DistributeWelfareAction.url, 'addelete_welfare_request'),
            url('^%s/(?P<student>\d+)/$' % actions.DistributeWelfareAction.url, 'distribute_welfare'),
        ) + super(WelfareModelAdmin, self).get_urls()
    
    def changelist_view(self, request, extra_context=None):
        if request.user.is_superuser or request.user.has_perm(actions.DistributeWelfareAction.permission):
            extra_context = _update_context(extra_context, {
                "actions_href": "../../actions/",
                "actions": [{
                    "href": actions.DistributeWelfareAction.url + "/",
                    "verbose_name": actions.DistributeWelfareAction.verbose_name,
                }]
            })
        return super(WelfareModelAdmin, self).changelist_view(request, extra_context)
    
    def has_view_permission(self, request, obj=None):
        if obj is not None and obj.student.user == request.user:
            return True
        return super(WelfareModelAdmin, self).has_view_permission(request, obj)

class WelfareRequestModelAdmin(AristoclesModelAdmin):
    
    actions = (actions.distribute_welfare,)
    
    def has_view_permission(self, request, obj=None):
        if obj is not None and obj.student.user == request.user:
            return True
        return super(WelfareRequestModelAdmin, self).has_view_permission(request, obj)
    
    def changelist_view(self, request, extra_context=None):
        if request.user.is_superuser or request.user.has_perm(actions.SendWelfareRequestAction.permission):
            extra_context = _update_context(extra_context, {
                "actions_href": "../../actions/",
                "actions": [{
                    "href": actions.SendWelfareRequestAction.url + "/",
                    "verbose_name": actions.SendWelfareRequestAction.verbose_name,
                }]
            })
        return super(WelfareRequestModelAdmin, self).changelist_view(request, extra_context)
    
    def get_urls(self):
        return patterns('aristocles.dummy.views',
            url('^' + actions.SendWelfareRequestAction.url + '/$', 'send_request'),
        ) + super(WelfareRequestModelAdmin, self).get_urls()

_model_admins = {
    models.Scholarship: ScholarshipModelAdmin,
    models.Session: SessionModelAdmin,
    models.Speciality: SpecialityModelAdmin,
    models.Student: StudentModelAdmin,
    models.StudentClass: StudentClassModelAdmin,
    models.StudentGroup: StudentGroupModelAdmin,
    models.Welfare: WelfareModelAdmin,
    models.WelfareRequest: WelfareRequestModelAdmin,
}

class AristoclesAdminSite(admin.sites.AdminSite):
    
    @never_cache
    def index(self, request, extra_context=None):
        acts = actions.get_actions(request.user)
        for act in acts:
            act["href"] = "%s/%s/%s/" % (act["model"]._meta.app_label, act["model"]._meta.module_name, act["url"])
        extra_context = _update_context(extra_context, {
            "actions": acts,
            "actions_href": "actions/",
        })
        return super(AristoclesAdminSite, self).index(request, extra_context)
    
    def get_urls(self):
        return patterns('aristocles.dummy.views',
            url(r'^actions/$', 'action_list')
        ) + super(AristoclesAdminSite, self).get_urls()

def autoregister():
    app_models = get_app('dummy')
    for model in get_models(app_models):
        admin.site.register(model, _model_admins.get(model, AristoclesModelAdmin))
    admin.site.register(Group, GroupAdmin)
    admin.site.register(User, UserAdmin)

admin.site = AristoclesAdminSite()
autoregister()
